const bcrypt = require('bcryptjs');
const { User, Tenant } = require('../models');
const jwtConfig = require('../config/jwt');
const { nanoid } = require('nanoid');

class AuthService {
  // 用户注册
  async register(registrationData) {
    const { tenantId, email, password, firstName, lastName, role = 'user' } = registrationData;
    
    try {
      // 验证租户是否存在且活跃
      const tenant = await Tenant.findByTenantId(tenantId);
      if (!tenant) {
        throw new Error('Tenant not found');
      }
      
      if (tenant.status !== 'active') {
        throw new Error('Tenant is not active');
      }
      
      // 检查邮箱是否已存在
      const existingUser = await User.findByTenantAndEmail(tenantId, email);
      if (existingUser) {
        throw new Error('Email already registered in this tenant');
      }
      
      // 检查用户数量限制
      const userCount = await User.countDocuments({ tenantId });
      if (userCount >= tenant.settings.limits.users) {
        throw new Error('User limit reached for this tenant');
      }
      
      // 创建新用户
      const user = new User({
        tenantId,
        email: email.toLowerCase(),
        password, // 密码会在 pre-save 中间件中自动哈希
        firstName,
        lastName,
        role,
        status: 'pending' // 需要邮箱验证
      });
      
      // 生成邮箱验证令牌
      const verificationToken = user.generateEmailVerificationToken();
      
      await user.save();
      
      // 返回用户信息（不包含敏感数据）
      return {
        user: {
          id: user._id,
          tenantId: user.tenantId,
          email: user.email,
          firstName: user.firstName,
          lastName: user.lastName,
          fullName: user.fullName,
          role: user.role,
          status: user.status
        },
        verificationToken,
        message: 'User registered successfully. Please verify your email.'
      };
      
    } catch (error) {
      throw new Error(`Registration failed: ${error.message}`);
    }
  }
  
  // 用户登录
  async login(loginData) {
    const { tenantId, email, password, rememberMe = false } = loginData;
    
    try {
      // 验证租户
      const tenant = await Tenant.findByTenantId(tenantId);
      if (!tenant) {
        throw new Error('Invalid tenant');
      }
      
      if (tenant.status !== 'active') {
        throw new Error('Tenant is not active');
      }
      
      // 查找用户
      const user = await User.findByTenantAndEmail(tenantId, email);
      if (!user) {
        throw new Error('Invalid credentials');
      }
      
      // 检查账户锁定状态
      if (user.isLocked) {
        throw new Error('Account is locked due to too many failed login attempts');
      }
      
      // 验证密码
      const isPasswordValid = await user.comparePassword(password);
      if (!isPasswordValid) {
        // 增加登录尝试次数
        await user.incLoginAttempts();
        throw new Error('Invalid credentials');
      }
      
      // 检查用户状态
      if (user.status !== 'active') {
        throw new Error(`Account is ${user.status}`);
      }
      
      // 记录成功登录
      await user.recordLogin();
      
      // 生成令牌
      const tokens = jwtConfig.generateTokenPair(user);
      
      return {
        user: {
          id: user._id,
          tenantId: user.tenantId,
          email: user.email,
          firstName: user.firstName,
          lastName: user.lastName,
          fullName: user.fullName,
          role: user.role,
          status: user.status,
          lastLogin: user.security.lastLogin
        },
        tokens,
        tenant: {
          id: tenant._id,
          tenantId: tenant.tenantId,
          name: tenant.name,
          domain: tenant.domain,
          plan: tenant.plan
        }
      };
      
    } catch (error) {
      throw new Error(`Login failed: ${error.message}`);
    }
  }
  
  // 刷新令牌
  async refreshToken(refreshToken) {
    try {
      // 验证刷新令牌
      const decoded = jwtConfig.verifyRefreshToken(refreshToken);
      
      // 查找用户
      const user = await User.findById(decoded.sub);
      if (!user) {
        throw new Error('User not found');
      }
      
      // 验证租户ID匹配
      if (user.tenantId !== decoded.tenantId) {
        throw new Error('Tenant mismatch');
      }
      
      // 检查用户状态
      if (user.status !== 'active') {
        throw new Error('User account is not active');
      }
      
      // 检查账户锁定状态
      if (user.isLocked) {
        throw new Error('User account is locked');
      }
      
      // 生成新的令牌对
      const tokens = jwtConfig.generateTokenPair(user);
      
      return {
        tokens,
        user: {
          id: user._id,
          tenantId: user.tenantId,
          email: user.email,
          role: user.role
        }
      };
      
    } catch (error) {
      throw new Error(`Token refresh failed: ${error.message}`);
    }
  }
  
  // 邮箱验证
  async verifyEmail(verificationToken) {
    try {
      const user = await User.findByEmailVerificationToken(verificationToken);
      if (!user) {
        throw new Error('Invalid or expired verification token');
      }
      
      await user.verifyEmail();
      
      return {
        message: 'Email verified successfully',
        user: {
          id: user._id,
          email: user.email,
          status: user.status
        }
      };
      
    } catch (error) {
      throw new Error(`Email verification failed: ${error.message}`);
    }
  }
  
  // 请求密码重置
  async requestPasswordReset(tenantId, email) {
    try {
      const user = await User.findByTenantAndEmail(tenantId, email);
      if (!user) {
        // 为了安全，不透露用户是否存在
        return {
          message: 'If the email exists, a password reset link has been sent'
        };
      }
      
      const resetToken = user.generatePasswordResetToken();
      await user.save();
      
      return {
        resetToken, // 在实际应用中，这应该通过邮件发送
        message: 'Password reset token generated'
      };
      
    } catch (error) {
      throw new Error(`Password reset request failed: ${error.message}`);
    }
  }
  
  // 重置密码
  async resetPassword(resetToken, newPassword) {
    try {
      const user = await User.findByPasswordResetToken(resetToken);
      if (!user) {
        throw new Error('Invalid or expired reset token');
      }
      
      await user.resetPassword(newPassword);
      
      return {
        message: 'Password reset successfully',
        user: {
          id: user._id,
          email: user.email
        }
      };
      
    } catch (error) {
      throw new Error(`Password reset failed: ${error.message}`);
    }
  }
  
  // 修改密码
  async changePassword(userId, currentPassword, newPassword) {
    try {
      const user = await User.findById(userId);
      if (!user) {
        throw new Error('User not found');
      }
      
      // 验证当前密码
      const isCurrentPasswordValid = await user.comparePassword(currentPassword);
      if (!isCurrentPasswordValid) {
        throw new Error('Current password is incorrect');
      }
      
      // 设置新密码
      await user.setPassword(newPassword);
      await user.save();
      
      return {
        message: 'Password changed successfully'
      };
      
    } catch (error) {
      throw new Error(`Password change failed: ${error.message}`);
    }
  }
  
  // 验证令牌
  async validateToken(token) {
    try {
      const userInfo = jwtConfig.extractUserInfo(token);
      if (!userInfo) {
        throw new Error('Invalid token');
      }
      
      // 验证用户是否仍然存在且活跃
      const user = await User.findById(userInfo.userId);
      if (!user || user.status !== 'active' || user.isLocked) {
        throw new Error('User is not active');
      }
      
      return {
        valid: true,
        user: userInfo
      };
      
    } catch (error) {
      return {
        valid: false,
        error: error.message
      };
    }
  }
  
  // 登出（可以实现令牌黑名单）
  async logout(token) {
    try {
      // 在实际应用中，可以将令牌添加到黑名单
      // 这里只是简单返回成功消息
      
      return {
        message: 'Logged out successfully'
      };
      
    } catch (error) {
      throw new Error(`Logout failed: ${error.message}`);
    }
  }
  
  // 获取用户会话信息
  async getSessionInfo(userId) {
    try {
      const user = await User.findById(userId).select('-password -security.passwordResetToken -security.twoFactorSecret');
      if (!user) {
        throw new Error('User not found');
      }
      
      const tenant = await Tenant.findByTenantId(user.tenantId);
      
      return {
        user: {
          id: user._id,
          tenantId: user.tenantId,
          email: user.email,
          firstName: user.firstName,
          lastName: user.lastName,
          fullName: user.fullName,
          role: user.role,
          status: user.status,
          profile: user.profile,
          preferences: user.preferences,
          permissions: user.permissions,
          lastLogin: user.security.lastLogin
        },
        tenant: tenant ? {
          id: tenant._id,
          tenantId: tenant.tenantId,
          name: tenant.name,
          domain: tenant.domain,
          plan: tenant.plan,
          settings: tenant.settings
        } : null
      };
      
    } catch (error) {
      throw new Error(`Failed to get session info: ${error.message}`);
    }
  }
}

module.exports = new AuthService();